﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.Storage.RetryPolicies;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Queue;
using Microsoft.WindowsAzure.Storage.Queue.Protocol;

namespace cloudMPI
{
    public class QueueHelper
    {
        public CloudStorageAccount Account;
        public CloudQueueClient QueueClient;

        // Constructor - pass in a storage connection string.

        public QueueHelper(string connectionString)
        {
            Account = CloudStorageAccount.Parse(connectionString);

            QueueClient = Account.CreateCloudQueueClient();
            QueueClient.RetryPolicy = new LinearRetry(TimeSpan.Zero, 4);
        }

        // List queues.
        // Return true on success, false if not found, throw exception on error.

        public bool ListQueues(out List<CloudQueue> queueList)
        {
            queueList = new List<CloudQueue>();

            try
            {
                IEnumerable<CloudQueue> queues = QueueClient.ListQueues();
                if (queues != null)
                {
                    queueList.AddRange(queues);
                }
                return true;
            }
            catch (StorageException ex)
            {

                if ((int)ex.RequestInformation.HttpStatusCode == 404)
                {
                    return false;
                }

                throw;
            }
        }

        // Create a queue. 
        // Return true on success, false if already exists, throw exception on error.

        public bool CreateQueue(string queueName)
        {
            try
            {
                CloudQueue queue = QueueClient.GetQueueReference(queueName);
                queue.CreateIfNotExists();
                return true;
            }
            catch (StorageException ex)
            {

                if ((int)ex.RequestInformation.HttpStatusCode == 404)
                {
                    return false;
                }

                throw;
            }
        }

        // Delete a queue. 
        // Return true on success, false if not found, throw exception on error.

        public bool DeleteQueue(string queueName)
        {
            try
            {
                CloudQueue queue = QueueClient.GetQueueReference(queueName);
                queue.DeleteIfExists();
                return true;
            }
            catch (StorageException ex)
            {
                if ((int)ex.RequestInformation.HttpStatusCode == 404)
                {
                    return false;
                }

                throw;
            }
        }

        // Peek the next message from a queue. 
        // Return true on success (message available), false if no message or no queue, throw exception on error.

        public bool PeekMessage(string queueName, out CloudQueueMessage message)
        {
            message = null;
            try
            {
                CloudQueue queue = QueueClient.GetQueueReference(queueName);
                message = queue.PeekMessage();
                return message != null;
            }
            catch (StorageException ex)
            {

                if ((int)ex.RequestInformation.HttpStatusCode == 404)
                {
                    return false;
                }

                throw;
            }
        }

        // Retrieve the next message from a queue. 
        // Return true on success (message available), false if no message or no queue, throw exception on error.

        public bool GetMessage(string queueName, out CloudQueueMessage message)
        {
            message = null;

            try
            {
                CloudQueue queue = QueueClient.GetQueueReference(queueName);
                message = queue.GetMessage(new TimeSpan(1, 59, 1));
                return message != null;
            }
            catch (StorageException ex)
            {
                if ((int)ex.RequestInformation.HttpStatusCode == 404)
                {
                    return false;
                }

                throw ex;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        // Retrieve the next n messages from a queue. 
        // Return true on success (message available), false if no message or no queue, throw exception on error.

        public bool GetMessage(string queueName, int messageCount, ref IEnumerable<CloudQueueMessage> messages)
        {
            messages = null;
            try
            {
                CloudQueue queue = QueueClient.GetQueueReference(queueName);
                messages = queue.GetMessages(messageCount, new TimeSpan(2, 0, 0));
                return messages != null;
            }
            catch (StorageException ex)
            {

                if ((int)ex.RequestInformation.HttpStatusCode == 404)
                {
                    System.Diagnostics.Trace.WriteLine("404 Exception in Get Message" + ex.Message);
                    return false;
                }
                throw;
            }
        }

        // Retrieve the next message from a queue. 
        // Return true on success (message available), false if no message or no queue, throw exception on error.

        public bool GetApproxMessageCount(string queueName, out int ApproxMessageCount)
        {
            ApproxMessageCount = 0;
            try
            {
                CloudQueue queue = QueueClient.GetQueueReference(queueName);
                queue.FetchAttributes();
                int? msgCount = queue.ApproximateMessageCount;
                ApproxMessageCount = (int)msgCount;
                return (ApproxMessageCount >= 0);
            }
            catch (StorageException ex)
            {

                if ((int)ex.RequestInformation.HttpStatusCode == 404)
                {
                    return false;
                }
                throw;
            }
            catch (Exception ex)
            {
                return false;
            }
            
        }
        // Create or update a blob. 
        // Return true on success, false if already exists, throw exception on error.

        public bool PutMessage(string queueName, CloudQueueMessage message)
        {
            try
            {
                TimeSpan ts = new TimeSpan(1, 0, 0);
                CloudQueue queue = QueueClient.GetQueueReference(queueName);
                queue.AddMessage(message, ts);
                return true;
            }
            catch (StorageException ex)
            {

                if ((int)ex.RequestInformation.HttpStatusCode == 404)
                {
                    System.Diagnostics.Trace.WriteLine("Could not write a message to the queue " + queueName);
                    return false;
                }

                throw;
            }
        }

        // Clear all messages from a queue. 
        // Return true on success, false if already exists, throw exception on error.

        public bool ClearMessages(string queueName)
        {
            try
            {
                CloudQueue queue = QueueClient.GetQueueReference(queueName);
                queue.Clear();
                return true;
            }
            catch (StorageException ex)
            {

                if ((int)ex.RequestInformation.HttpStatusCode == 404)
                {
                    return false;
                }

                throw;
            }
        }

        // Delete a previously read message. 
        // Return true on success, false if already exists, throw exception on error.

        public bool DeleteMessage(string queueName, CloudQueueMessage message)
        {
            try
            {
                CloudQueue queue = QueueClient.GetQueueReference(queueName);
                if (message != null)
                {
                    queue.DeleteMessage(message);
                }
                return true;
            }
            catch (StorageException ex)
            {

                if ((int)ex.RequestInformation.HttpStatusCode == 404)
                {
                    return false;
                }

                throw;
            }
        }

    }
}


